/**
 *  gcc -O2 -pthread -o tlsf_mt_test tlsf_mt_test.c ../tlsf/tlsf.c -I../tlsf
 */

#include "tlsf.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <time.h>

#define POOL_SIZE      (1024 * 1024)  // 1MB
#define OPERATIONS     100000
#define MAX_PTRS       10000
#define MIN_ALLOC_SIZE 8
#define MAX_ALLOC_SIZE 512
#define THREAD_COUNT   4
#define PRINT_INTERVAL 2  // 每隔2秒打印内存状态

static void* tlsf_pool = NULL;
static tlsf_t tlsf = NULL;
static pthread_mutex_t tlsf_mutex = PTHREAD_MUTEX_INITIALIZER;

typedef struct
{
    void* ptrs[MAX_PTRS];
    size_t count;
} thread_context_t;

void* thread_func(void* arg)
{
    thread_context_t* ctx = (thread_context_t*)arg;
    srand((unsigned int)pthread_self());

    for (int i = 0;  i < OPERATIONS;  i++) {
        int op = rand() % 100;

        if (op < 70) {                                  // 70% malloc
            size_t size = MIN_ALLOC_SIZE + (rand() % (MAX_ALLOC_SIZE - MIN_ALLOC_SIZE + 1));
            pthread_mutex_lock(&tlsf_mutex);
            void* p = tlsf_malloc(tlsf, size);
            pthread_mutex_unlock(&tlsf_mutex);

            if (p && ctx->count < MAX_PTRS) {
                ctx->ptrs[ctx->count++] = p;
            }
        }
        else if (ctx->count > 0) {                      // 30% free
            size_t idx = rand() % ctx->count;
            void* p = ctx->ptrs[idx];

            pthread_mutex_lock(&tlsf_mutex);
            tlsf_free(tlsf, p);
            pthread_mutex_unlock(&tlsf_mutex);

            ctx->ptrs[idx] = ctx->ptrs[ctx->count - 1];
            ctx->ptrs[ctx->count - 1] = NULL;
            ctx->count--;
        }
    }

    // 最后清理掉剩余的指针
    for (size_t i = 0; i < ctx->count; ++i) {
        if (ctx->ptrs[i]) {
            pthread_mutex_lock(&tlsf_mutex);
            tlsf_free(tlsf, ctx->ptrs[i]);
            pthread_mutex_unlock(&tlsf_mutex);
        }
    }

    return NULL;
}

void* monitor_func(void* arg)
{
    (void)arg;

    while (1) {
        sleep(PRINT_INTERVAL);
        pthread_mutex_lock(&tlsf_mutex);

        size_t used = tlsf_used_size(tlsf);      // TLSF原版没有这个，需要你在tlsf里加一点辅助函数
        size_t total = tlsf_total_size(tlsf);    // 同上

        pthread_mutex_unlock(&tlsf_mutex);

        printf("[Monitor] Used: %zu bytes / Total: %zu bytes\n", used, total);
    }
    return NULL;
}

int main()
{
    tlsf_pool = malloc(POOL_SIZE);
    if (! tlsf_pool) {
        printf("Failed to allocate memory pool.\n");
        return 1;
    }

    tlsf = tlsf_create_with_pool(tlsf_pool, POOL_SIZE);
    if (! tlsf) {
        printf("Failed to create TLSF pool.\n");
        free(tlsf_pool);
        return 1;
    }

    pthread_t threads[THREAD_COUNT];
    thread_context_t contexts[THREAD_COUNT];

    memset(contexts, 0, sizeof(contexts));

    // 启动监控线程
    pthread_t monitor;
    pthread_create(&monitor, NULL, monitor_func, NULL);

    clock_t start_time = clock();

    // 启动工作线程
    for (int i = 0; i < THREAD_COUNT; ++i) {
        pthread_create(&threads[i], NULL, thread_func, &contexts[i]);
    }

    for (int i = 0; i < THREAD_COUNT; ++i) {
        pthread_join(threads[i], NULL);
    }

    clock_t end_time = clock();
    double elapsed_secs = (double)(end_time - start_time) / CLOCKS_PER_SEC;

    printf("Multithreaded test completed in %.6f seconds.\n", elapsed_secs);

    tlsf_destroy(tlsf);
    free(tlsf_pool);

    return 0;
}
